﻿using Demo.Application.DbContexts;
using Demo.Domains.Entities.Sys;
using Microsoft.Extensions.DependencyInjection;
using PmSoft.Cache.Abstractions;
using PmSoft.Core;
using PmSoft.Data.Abstractions;
using PmSoft.Data.SqlSugar.Repositories;

namespace Demo.Application.Services.User;

/// <summary>
/// 用户仓储类，提供用户数据的访问和缓存管理
/// </summary>
[Inject(ServiceLifetime.Scoped)]
public class UserRepository : CacheRepository<AppDbContext, SysUser, int>
{
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="dbContext">应用程序数据库上下文</param>
    /// <param name="applicationContext">应用程序上下文</param>
    public UserRepository(AppDbContext dbContext,
        IApplicationContext applicationContext)
        : base(dbContext, applicationContext)
    {
    }

    /// <summary>
    /// 获取指定部门的所有用户
    /// </summary>
    /// <param name="deptId">部门ID</param>
    /// <returns>用户集合</returns>
    /// <remarks>
    /// 该方法使用缓存机制，通过部门区域版本号来管理缓存
    /// 缓存键格式：Users:{deptId}:{areaVersion}
    /// </remarks>
    public async ValueTask<IEnumerable<SysUser>> GetUsersAsync(int deptId)
    {
        int areaVersion = await CacheVersionService.GetAreaVersionAsync(m => m.DeptId, deptId);
        return await GetTopEntitiesWithCacheAsync(1000,
            CachingExpirationType.ObjectCollection,
            () => $"Users:{deptId}:{areaVersion}",
            queryable => queryable.Where(m => m.DeptId == deptId));
    }

    /// <summary>
    /// 分页查询用户列表
    /// </summary>
    /// <param name="query">查询条件</param>
    /// <param name="pageIndex">页码，默认为1</param>
    /// <param name="pageSize">每页大小，默认为20</param>
    /// <returns>分页后的用户列表</returns>
    /// <remarks>
    /// 支持按部门ID和用户名称进行筛选
    /// 结果按用户ID降序排序
    /// </remarks>
    public async ValueTask<IPagedList<SysUser>> UserPagingAsync(UserQuery query, int pageIndex = 1, int pageSize = 20)
    {
        return await GetPagedEntitiesAsync(queryable =>
        {
            if (query.DeptId.HasValue)
                queryable = queryable.Where(it => it.DeptId == query.DeptId);
            if (!string.IsNullOrWhiteSpace(query.Name))
                queryable = queryable.Where(it => it.Name.Contains(query.Name));

            queryable = queryable.OrderByDescending(it => it.Id);

            //return q.InnerJoin<SysDept>((m, d) => m.DeptId == d.Id)
            //.Where((m, d) => m.DeptId == 1 && d.Id == 1)
            //.OrderByDescending((m, d) => m.Id);

            return queryable;
        },
           pageIndex,
           pageSize
           );
    }
}
